#include "Parser.h"

u64 incrementalID;
std::map<u64, Parser*> parserList;

Parser::Parser(agr_user *user, Logic *logic){
	this->user = user;
	this->logic = logic;
	this->sock = user->socket;
	this->totalRead = 0;
	this->pendingRead = 0;
}

void Parser::setStatus(parser_status status){
	this->status = status;
}

agr_file *Parser::getFile(){
	return this->file;
}

agr_user *Parser::getUser(){
	return this->user;
}

Logic *Parser::getLogic(){
	return this->logic;
}

SOCKET Parser::getSocket(){
	return this->sock;
}

parser_status Parser::getStatus(){
	return this->status;
}

bool Parser::processPacket(Packet *packet, int bRecv){
	if(!packet)
		return false;

	/*totalRead = packet->data.size;
	if(pendingRead == 0)
	{
		pendingRead = totalRead;
	}
	else
	{
		pendingRead -= bRecv;
	}
	viewer->print("RECV [%.4X]: %d %d\n", packet->data.opcode, totalRead, pendingRead);
	*/

	if(packet->data.size > 0x2000) //(8192)
		return false;

	switch(packet->data.opcode){
		case WELCOME:
			return welcomeUser();
			break;

		case WELCOME_RESP:
			return addUser();
			break;

		case CON_ERROR:			
			return checkDisconnect();
			break;

		case FILES_RETRIEVE:
			return retrieveFiles();
			break;

		case FILES_RETRIEVE_RESP:
			return getFilesList(packet);
			break;

		case PING:
			return true;
			break;

		default:
			break;
	}

	return true;
}

bool Parser::welcomeUser(){
	Packet packet;
	memset(&(packet.data), 0, sizeof(Packet::data_));
	packet.data.opcode = 0x5001;

	send(this->sock, (const char*)packet.getPacket(), packet.data.size + sizeof(u32), 0);

	return true;
}

bool Parser::addUser(){
	agr_user *user = this->getUser();
	this->getLogic()->addUser(user);

	return true;
}

bool Parser::checkDisconnect(){
	u8 b[] = {0x00, 0x00, 0xC0, 0xCC};
	int s = send(this->getSocket(), (const char*)b, 4, 0);

	if(s <= 0)
	{
		this->getLogic()->removeUser(this->getUser());
		this->setStatus(STATUS_DISCONNECTED);

		return false;
	}

	return true;
}

bool Parser::retrieveFiles(u64 arg0){
	viewer->print("Retrieving files from user: %lld :: %d\n", this->getUser()->ID, this->logic->getUser()->filesList.size());

	Packet packet;
	packet.data.opcode = FILES_RETRIEVE_RESP;

	agr_user *luser = this->logic->getUser();
	packet.write<u64>(luser->filesList.size());
	
	for(int i = 0; i < luser->filesList.size(); i++){
		packet.write<u64>(luser->filesList[i]->fID);
		packet.writeString(	agr_utils::getName(luser->filesList[i]->path) );
	}

	packet.setSize();
	
	send(this->getSocket(), (const char*)packet.getPacket(), packet.data.size + sizeof(u32), 0);

	return true;
}

bool Parser::getFilesList(Packet *packet){
	u64 numFiles = packet->read<u64>();

	viewer->print("Files (%lld):\n", numFiles);
	for(u64 i = 0; i < numFiles; i++){
		u64 id = packet->read<u64>();
		char *name = packet->readString();
		viewer->print("\t%lld: %s\n", id, name);
	}

	return true;
}

#ifdef VIEWER_CONSOLE_MODE
	bool Parser::requestUserID(u64 arg0){
		viewer->print("User ID: ");
		int id = atoi(viewer->input());
		Logic *logic = this->getLogic();

		if(parserList[id] != NULL){
			parserList[id]->retrieveFiles();
		}

		return false;
	};
#endif
